using System.Collections.Generic;
using TestCases.CompareAssert.Core.Comparers.Interfaces;
using TestCases.CompareAssert.Core.Interfaces;

namespace TestCases.CompareAssert.Core.Comparers.Basic
{
    public class SideIndependentComparer<TComparer> : IObjectComparer where TComparer: IObjectComparer
    {
        private readonly bool _forceTwoSide;

        public SideIndependentComparer() : this(false)
        {
        }

        public SideIndependentComparer(bool forceTwoSide)
        {
            _forceTwoSide = forceTwoSide;
        }

        public SideIndependentComparer(TComparer comparer) : this(false, comparer)
        {
        }

        public SideIndependentComparer(bool forceTwoSide, TComparer comparer)
        {
            _forceTwoSide = forceTwoSide;
            Comparer = comparer;
        }

        public TComparer Comparer { get; set; }

        public string Name
        {
            get { return "SideIndependentComparer"; }
        }

        public IResultBuilder Compare(ICompareContext context)
        {
            var builder = Comparer.Compare(context);
            switch (builder.GetStatus())
            {
                case CompareStatus.Equals:
                    return builder;

                case CompareStatus.NotEquals:
                    if (!_forceTwoSide)
                    {
                        return builder;
                    }
                    break;
            }
            var results = new List<IResultProvider> {builder};
            return this.IsStatusResult(Comparer.CompareAndAddResult(context.Reverse(), results).GetStatus(), context, results);
        }
    }
    
    public class SideIndependentComparer: SideIndependentComparer<IObjectComparer>
    {
        public SideIndependentComparer()
        {
        }

        public SideIndependentComparer(bool forceTwoSide) : base(forceTwoSide)
        {
        }

        public SideIndependentComparer(IObjectComparer comparer) : base(comparer)
        {
        }

        public SideIndependentComparer(bool forceTwoSide, IObjectComparer comparer) : base(forceTwoSide, comparer)
        {
        }       
    }
}